home *** CD-ROM | disk | FTP | other *** search
/ United Public Domain Gold 2 / United Public Domain Gold 2.iso / music_utilities / pt030.dms / pt030.adf / Less / Src / option.c < prev    next >
C/C++ Source or Header  |  1987-06-15  |  9KB  |  430 lines

  1. /*
  2.  * Process command line options.
  3.  * Each option is a single letter which controls a program variable.
  4.  * The options have defaults which may be changed via
  5.  * the command line option, or toggled via the "-" command.
  6.  */
  7.  
  8. #include "less.h"
  9.  
  10. #define    toupper(c)    ((c)-'a'+'A')
  11.  
  12. #define    END_OPTION_STRING    ('$')
  13.  
  14. /*
  15.  * Types of options.
  16.  */
  17. #define    BOOL        01    /* Boolean option: 0 or 1 */
  18. #define    TRIPLE        02    /* Triple-valued option: 0, 1 or 2 */
  19. #define    NUMBER        04    /* Numeric option */
  20. #define    REPAINT        040    /* Repaint screen after toggling option */
  21. #define    NO_TOGGLE    0100    /* Option cannot be toggled with "-" cmd */
  22.  
  23. /*
  24.  * Variables controlled by command line options.
  25.  */
  26. public int p_nbufs, f_nbufs;    /* Number of buffers.  There are two values,
  27.                    one used for input from a pipe and 
  28.                    the other for input from a file. */
  29. public int clean_data;        /* Can we assume the data is "clean"? 
  30.                    (That is, free of nulls, etc) */
  31. public int quiet;        /* Should we suppress the audible bell? */
  32. public int top_search;        /* Should forward searches start at the top 
  33.                    of the screen? (alternative is bottom) */
  34. public int top_scroll;        /* Repaint screen from top?
  35.                    (alternative is scroll from bottom) */
  36. public int pr_type;        /* Type of prompt (short, medium, long) */
  37. public int bs_mode;        /* How to process backspaces */
  38. public int know_dumb;        /* Don't complain about dumb terminals */
  39. public int quit_at_eof;        /* Quit after hitting end of file twice */
  40. public int squeeze;        /* Squeeze multiple blank lines into one */
  41. public int tabstop;        /* Tab settings */
  42. public int back_scroll;        /* Repaint screen on backwards movement */
  43. public int twiddle;        /* Display "~" for lines after EOF */
  44.  
  45. extern char *prproto[];
  46. extern int nbufs;
  47. extern int sc_window;
  48. extern char *first_cmd;
  49. extern char *every_first_cmd;
  50. #if LOGFILE
  51. extern char *namelogfile;
  52. extern int force_logfile;
  53. #endif
  54.  
  55. #define    DEF_F_NBUFS    5    /* Default for f_nbufs */
  56. #define    DEF_P_NBUFS    12    /* Default for p_nbufs */
  57.  
  58. static struct option
  59. {
  60.     char oletter;        /* The controlling letter (a-z) */
  61.     char otype;        /* Type of the option */
  62.     int odefault;        /* Default value */
  63.     int *ovar;        /* Pointer to the associated variable */
  64.     char *odesc[3];        /* Description of each value */
  65. } option[] =
  66. {
  67.     { 'c', TRIPLE, 0, &top_scroll,
  68.         { "Repaint by scrolling from bottom of screen",
  69.           "Repaint by clearing each line",
  70.           "Repaint by painting from top of screen"
  71.         }
  72.     },
  73.     { 'd', BOOL|NO_TOGGLE, 0, &know_dumb,
  74.         { NULL, NULL, NULL}
  75.     },
  76.     { 'e', TRIPLE, 0, &quit_at_eof,
  77.         { "Don't quit at end-of-file",
  78.           "Quit at end-of-file",
  79.           "Quit immediately at end-of-file"
  80.         }
  81.     },
  82.     { 'f', BOOL, 0, &clean_data,
  83.         { "Don't assume data is clean",
  84.           "Assume data is clean",
  85.           NULL
  86.         }
  87.     },
  88.     { 'h', NUMBER, 10, &back_scroll,
  89.         { "Backwards scroll limit is %d lines",
  90.           NULL, NULL
  91.         }
  92.     },
  93.     { 'm', TRIPLE, 2, &pr_type,
  94.         { "Short prompt",
  95.           "Medium prompt",
  96.           "Long prompt"
  97.         }
  98.     },
  99.     { 'q', TRIPLE, 0, &quiet,
  100.         { "Ring the bell for errors AND at eof/bof",
  101.           "Ring the bell for errors but not at eof/bof",
  102.           "Never ring the bell"
  103.         }
  104.     },
  105.     { 'u', TRIPLE|REPAINT, 0, &bs_mode,
  106.  
  107.         { "Underlined text displayed in underline mode",
  108.           "Backspaces cause overstrike",
  109.           "Backspaces print as ^H"
  110.         }
  111.     },
  112.     { 's', BOOL|REPAINT, 0, &squeeze,
  113.         { "Don't squeeze multiple blank lines",
  114.           "Squeeze multiple blank lines",
  115.           NULL
  116.         }
  117.     },
  118.     { 't', BOOL, 1, &top_search,
  119.         { "Forward search starts from bottom of screen",
  120.           "Forward search starts from top of screen",
  121.           NULL
  122.         }
  123.     },
  124.     { 'w', BOOL|REPAINT, 1, &twiddle,
  125.         { "Display nothing for lines after end-of-file",
  126.           "Display ~ for lines after end-of-file",
  127.           NULL
  128.         }
  129.     },
  130.     { 'x', NUMBER|REPAINT, 8, &tabstop,
  131.         { "Tab stops every %d spaces", 
  132.           NULL, NULL 
  133.         }
  134.     },
  135.     { 'z', NUMBER|REPAINT, -1, &sc_window,
  136.         { "Scroll window size is %d lines",
  137.           NULL, NULL
  138.         }
  139.     },
  140.     { '\0' }
  141. };
  142.  
  143. public char all_options[64];    /* List of all valid options */
  144.  
  145. /*
  146.  * Initialize each option to its default value.
  147.  */
  148.     public void
  149. init_option()
  150. {
  151.     register struct option *o;
  152.     register char *p;
  153.  
  154.     /*
  155.      * First do special cases, not in option table.
  156.      */
  157.     first_cmd = every_first_cmd = NULL;
  158.     f_nbufs = DEF_F_NBUFS;        /* -bf */
  159.     p_nbufs = DEF_P_NBUFS;        /* -bp */
  160.  
  161.     p = all_options;
  162.     *p++ = 'b';
  163.  
  164.     for (o = option;  o->oletter != '\0';  o++)
  165.     {
  166.         /*
  167.          * Set each variable to its default.
  168.          * Also make a list of all options, in "all_options".
  169.          */
  170.         *(o->ovar) = o->odefault;
  171.         *p++ = o->oletter;
  172.         if (o->otype & TRIPLE)
  173.             *p++ = toupper(o->oletter);
  174.     }
  175.     *p = '\0';
  176. }
  177.  
  178. /*
  179.  * Toggle command line flags from within the program.
  180.  * Used by the "-" command.
  181.  */
  182.     public void
  183. toggle_option(s)
  184.     char *s;
  185. {
  186.     int c;
  187.     register struct option *o;
  188.     char *msg;
  189.     int n;
  190.     int dorepaint;
  191.     char message[100];
  192.     char buf[5];
  193.  
  194.     c = *s++;
  195.  
  196.     /*
  197.      * First check for special cases not handled by the option table.
  198.      */
  199.     switch (c)
  200.     {
  201.     case 'b':
  202.         sprintf(message, "%d buffers", nbufs);
  203.         error(message);
  204.         return;
  205.     }
  206.  
  207.     msg = NULL;
  208.     for (o = option;  o->oletter != '\0';  o++)
  209.     {
  210.         if (o->otype & NO_TOGGLE)
  211.             continue;
  212.         dorepaint = (o->otype & REPAINT);
  213.         if ((o->otype & BOOL) && (o->oletter == c))
  214.         {
  215.             /*
  216.              * Boolean option: 
  217.              * just toggle it.
  218.              */
  219.             *(o->ovar) = ! *(o->ovar);
  220.         } else if ((o->otype & TRIPLE) && (o->oletter == c))
  221.         {
  222.             /*
  223.              * Triple-valued option with lower case letter:
  224.              * make it 1 unless already 1, then make it 0.
  225.              */
  226.             *(o->ovar) = (*(o->ovar) == 1) ? 0 : 1;
  227.         } else if ((o->otype & TRIPLE) && (toupper(o->oletter) == c))
  228.         {
  229.             /*
  230.              * Triple-valued option with upper case letter:
  231.              * make it 2 unless already 2, then make it 0.
  232.              */
  233.             *(o->ovar) = (*(o->ovar) == 2) ? 0 : 2;
  234.         } else if ((o->otype & NUMBER) && (o->oletter == c))
  235.         {
  236.             n = getnum(&s, '\0');
  237.             if (n < 0)
  238.             {
  239.                 /*
  240.                  * No number; just a query.
  241.                  * No need to repaint screen.
  242.                  */
  243.                 dorepaint = 0;
  244.             } else
  245.             {
  246.                 /*
  247.                  * Number follows the option letter.
  248.                  * Set the variable to that number.
  249.                  */
  250.                 *(o->ovar) = n;
  251.             }
  252.             sprintf(message, o->odesc[0], 
  253.                 (o->ovar == &back_scroll) ? 
  254.                 get_back_scroll() : *(o->ovar));
  255.             msg = message;
  256.         } else
  257.             continue;
  258.  
  259.         if (dorepaint)
  260.             repaint();
  261.         if (msg == NULL)
  262.             msg = o->odesc[*(o->ovar)];
  263.         error(msg);
  264.         return;
  265.     }
  266.  
  267.     if (control_char(c))
  268.         sprintf(buf, "^%c", carat_char(c));
  269.     else
  270.         sprintf(buf, "%c", c);
  271.     sprintf(message, "\"-%s\": no such flag.  Use one of \"%s\"", 
  272.         buf, all_options);
  273.     error(message);
  274. }
  275.  
  276. /*
  277.  * Scan to end of string or to an END_OPTION_STRING character.
  278.  * In the latter case, replace the char with a null char.
  279.  * Return a pointer to the remainder of the string, if any.
  280.  */
  281.     static char *
  282. optstring(s)
  283.     char *s;
  284. {
  285.     register char *p;
  286.  
  287.     for (p = s;  *p != '\0';  p++)
  288.         if (*p == END_OPTION_STRING)
  289.         {
  290.             *p = '\0';
  291.             return (p+1);
  292.         }
  293.     return (p);
  294. }
  295.  
  296. /* 
  297.  * Scan an argument (either from command line or from LESS environment 
  298.  * variable) and process it.
  299.  */
  300.     public void
  301. scan_option(s)
  302.     char *s;
  303. {
  304.     register struct option *o;
  305.     register int c;
  306.     char message[80];
  307.  
  308.     if (s == NULL)
  309.         return;
  310.  
  311.     next:
  312.     if (*s == '\0')
  313.         return;
  314.     switch (c = *s++)
  315.     {
  316.     case '-':
  317.     case ' ':
  318.     case '\t':
  319.     case END_OPTION_STRING:
  320.         goto next;
  321.     case '+':
  322.         if (*s == '+')
  323.             every_first_cmd = ++s;
  324.         first_cmd = s;
  325.         s = optstring(s);
  326.         goto next;
  327.     case 'P':
  328.         switch (*s)
  329.         {
  330.         case 'm':  prproto[PR_MEDIUM] = ++s;  break;
  331.         case 'M':  prproto[PR_LONG] = ++s;    break;
  332.         default:   prproto[PR_SHORT] = s;     break;
  333.         }
  334.         s = optstring(s);
  335.         goto next;
  336. #if LOGFILE
  337.     case 'L':
  338.         force_logfile = 1;
  339.         /* fall thru */
  340.     case 'l':
  341.         namelogfile = s;
  342.         s = optstring(s);
  343.         goto next;
  344. #endif
  345.     case 'b':
  346.         switch (*s)
  347.         {
  348.         case 'f':
  349.             s++;
  350.             f_nbufs = getnum(&s, 'b');
  351.             break;
  352.         case 'p':
  353.             s++;
  354.             p_nbufs = getnum(&s, 'b');
  355.             break;
  356.         default:
  357.             f_nbufs = p_nbufs = getnum(&s, 'b');
  358.             break;
  359.         }
  360.         goto next;
  361.     case '0':  case '1':  case '2':  case '3':  case '4':
  362.     case '5':  case '6':  case '7':  case '8':  case '9':
  363.         {
  364.             /*
  365.              * Handle special "more" compatibility form "-number"
  366.              * to set the scrolling window size.
  367.              */
  368.             s--;
  369.             sc_window = getnum(&s, '-');
  370.             goto next;
  371.         }
  372.     }
  373.  
  374.     for (o = option;  o->oletter != '\0';  o++)
  375.     {
  376.         if ((o->otype & BOOL) && (o->oletter == c))
  377.         {
  378.             *(o->ovar) = ! o->odefault;
  379.             goto next;
  380.         } else if ((o->otype & TRIPLE) && (o->oletter == c))
  381.         {
  382.             *(o->ovar) = (o->odefault == 1) ? 0 : 1;
  383.             goto next;
  384.         } else if ((o->otype & TRIPLE) && (toupper(o->oletter) == c))
  385.         {
  386.             *(o->ovar) = (o->odefault == 2) ? 0 : 2;
  387.             goto next;
  388.         } else if ((o->otype & NUMBER) && (o->oletter == c))
  389.         {
  390.             *(o->ovar) = getnum(&s, c);
  391.             goto next;
  392.         }
  393.     }
  394.  
  395.     sprintf(message, "\"-%c\": invalid flag", c);
  396.     error(message);
  397.     exit(1);
  398. }
  399.  
  400. /*
  401.  * Translate a string into a number.
  402.  * Like atoi(), but takes a pointer to a char *, and updates
  403.  * the char * to point after the translated number.
  404.  */
  405.     static int
  406. getnum(sp, c)
  407.     char **sp;
  408.     int c;
  409. {
  410.     register char *s;
  411.     register int n;
  412.     char message[80];
  413.  
  414.     s = *sp;
  415.     if (*s < '0' || *s > '9')
  416.     {
  417.         if (c == '\0')
  418.             return (-1);
  419.         sprintf(message, "number is required after -%c", c);
  420.         error(message);
  421.         exit(1);
  422.     }
  423.  
  424.     n = 0;
  425.     while (*s >= '0' && *s <= '9')
  426.         n = 10 * n + *s++ - '0';
  427.     *sp = s;
  428.     return (n);
  429. }
  430.